package com.xpec.c4.service.module.datacenter.player;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ms.game.characterInfo.CharacterInfoProcessor;
import com.ms.game.characterInfo.db.CharacterInfoLogDAO;
import com.ms.game.itembox.ItemChangeParam;
import com.ms.game.itembox.db.PlayerItemChangeLogModel;
import com.ms.service.error.ErrorCode;
import com.xpec.c4.game.character.PlayerManager;
import com.xpec.c4.game.datamanager.ResultNo;
import com.xpec.c4.game.datamanager.agent.money.ChangeCoin;
import com.xpec.c4.game.datamanager.agent.money.ChangeCoinLister;
import com.xpec.c4.game.datamanager.agent.money.CoinType;
import com.xpec.c4.game.datamanager.agent.money.MoneyChangeParam;
import com.xpec.c4.game.datamanager.agent.moneyItem.MoneyItemChangeParam;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.service.module.BasicServiceModule;
import com.xpec.c4.service.module.ServerProperties;
import com.xpec.c4.service.module.datacenter.DCAsyncCommand;
import com.xpec.c4.service.module.datacenter.player.db.PlayerMoneyChangeLogModel;

public class UpdatePlayerMoneyItemAsync extends DCAsyncCommand {

	private static final Log log = LogFactory.getLog(UpdatePlayerMoneyItemAsync.class);
	
	PlayerDataManager playerDataManager;
	BasicServiceModule currentModule;
	
	/**是不是網路來的要求**/
	private boolean isFromWeb = false;
	
	@Override
	public void asyncExecute() throws Exception {
		
		MoneyItemChangeParam param = (MoneyItemChangeParam) dataInfo.getData();

		try {
			PlayerManager.getInstance().updatePlayerMoneyItemToDB(param);
		} catch (RuntimeException e) {
			log.error("cannot update player money and item: " + param.getPlayerId(), e);
			resultCode = ResultNo.DB_OPERATION_FAILED;
			return;
		}

		if (param.getResult() == ErrorCode.SUCCESS)
		{
			if (param.getMoneyParam().getChangeCoinLister() != null &&
					param.getMoneyParam().getChangeCoinLister().getSize() != 0) {
				//有金錢才做判斷
				saveCharacterDaliyLog(param.getMoneyParam());
			}
						
			resultCode = ResultNo.OK;
		} else {
			resultCode = ResultNo.DB_OPERATION_FAILED;
		}

		return;
		
	}

	@Override
	public void execute() throws Exception {
		
		if(!isFromWeb){
			//如果是一般game的流程
			// callback
			if (playerDataManager != null) {
				playerDataManager.updatePlayerMoneyItemToDbCallback(resultCode, dataInfo, srcModuleID);
			}else{
				if(log.isErrorEnabled()){
					MoneyItemChangeParam param = (MoneyItemChangeParam) dataInfo.getData();
					String playerName = param.getPlayerName();
					String playerId = param.getPlayerId().toString();
					log.error(GameUtility.getCurMethodName() + " playerDataManager = null !!! 世界毀滅了!!!!! Name = " + playerName + " playerId = " + playerId);
				}
			}
		}

		saveItemLog();
		saveMoneyLog();
	}

	/**
	 * 寫道具log
	 */
	private void saveItemLog() {
		if (currentModule != null) {
			ArrayList<PlayerItemChangeLogModel> itemLogList = getItemLogs();			
			// 寫道具異動 log
			if (itemLogList != null && itemLogList.size() > 0) {
				for (PlayerItemChangeLogModel logModel : itemLogList) {
					currentModule.saveDbLog(logModel);
				}
			}			
		} // if (currentModule != null)
	}
	
	/**
	 * 取得 ItemItemChangeLog
	 * @param moneyItemParam
	 * @return
	 */
	public ArrayList<PlayerItemChangeLogModel> getItemLogs() {
		// 取得異動log
		MoneyItemChangeParam moneyItemParam = (MoneyItemChangeParam) dataInfo.getData();
		ItemChangeParam param = moneyItemParam.getItemParam();
		ArrayList<PlayerItemChangeLogModel> itemLogList = param.getLogModelList();
		return itemLogList;
	}
	
	
	/**
	 * 寫金錢異動log
	 */
	private void saveMoneyLog() {
	
		if (currentModule != null) {
			PlayerMoneyChangeLogModel model = getMoneyChangeLog();
			if (model != null) {
				// 寫 log
				//DbLogManager.saveLog(currentModule, param.getPlayerId(), model);
				
				//20160617 - 新增log至task 最後一條
				if (ServerProperties.isNeedSaveMoneyChangeLog(model)) {
					currentModule.saveDbLog(model);
				}

				currentModule.saveDbLog(CharacterInfoProcessor.convertDailyExchange(model));
			} // if (param.getResult() == ErrorCode.SUCCESS)
		} // if (currentModule != null)
	}
	
	/**
	 * 組成 PlayerMoneyChangeLogModel 
	 * @param param
	 * @return
	 */
	public PlayerMoneyChangeLogModel getMoneyChangeLog(){
		MoneyItemChangeParam moneyItemParam = (MoneyItemChangeParam) dataInfo.getData();
		MoneyChangeParam param = moneyItemParam.getMoneyParam();
		if(param.getResult() == ErrorCode.SUCCESS){
			PlayerMoneyChangeLogModel model = new PlayerMoneyChangeLogModel();
			model.setOrderId(param.getOrderId().toString());
			model.setAccountId(param.getAccountId().toString());
			model.setPlayerId(param.getPlayerId().toString());
			model.setPlayerName(param.getPlayerName());
			model.setUserType(param.getUserType());
			model.setGameHallId(param.getGameHallId());
			model.setGameHallName(param.getGameHallName());
			model.setChangeWay(param.getChangeWay().getId());
			model.setChangeWayDesc(param.getChangeWay().getDesc());

			// 填入各個幣別的結果
			ChangeCoinLister coinLister = param.getChangeCoinLister();
			Iterator<Map.Entry<CoinType, ChangeCoin>> it = coinLister.getListIterator();
			ChangeCoin coinInfo = coinLister.getNextCoin(it);
			while (coinInfo != null) {
				switch (coinInfo.getCoinType()) {
				case TRIAL:
					model.setTrialChangeValue(coinInfo.getChangeValue());
					model.setTrialBeforeChange(coinInfo.getCurrentValue());
					model.setTrialAfterChange(coinInfo.getNewValue());
					break;
				case GOLD:
					model.setGoldChangeValue(coinInfo.getChangeValue());
					model.setGoldBeforeChange(coinInfo.getCurrentValue());
					model.setGoldAfterChange(coinInfo.getNewValue());
					break;
				case LUCKY:
					model.setLuckyChangeValue(coinInfo.getChangeValue());
					model.setLuckyBeforeChange(coinInfo.getCurrentValue());
					model.setLuckyAfterChange(coinInfo.getNewValue());
					break;
				default:
					if (log.isErrorEnabled()) {
						log.error("write player(" + model.getPlayerName() + "|" + model.getPlayerId()
								+ ") money change log, unknow coin type: " + coinInfo.getCoinType().getDesc());
					}
					break;
				} // switch(.....)

				coinInfo = coinLister.getNextCoin(it);
			} // while(......)
			return model;
		}else {
			return null;
		}
	}

	public UpdatePlayerMoneyItemAsync(PlayerDataManager playerDataManager, BasicServiceModule currentModule) {
		super();
		this.playerDataManager = playerDataManager;
		this.currentModule = currentModule;
	}

	/**
	 * 記錄玩家基本資訊的每日log
	 */
	private void saveCharacterDaliyLog(MoneyChangeParam param) {
		ChangeCoinLister coinLister = param.getChangeCoinLister();
		Iterator<Map.Entry<CoinType, ChangeCoin>> it = coinLister.getListIterator();
		ChangeCoin coinInfo = coinLister.getNextCoin(it);
		while (coinInfo != null) {
			// 如果是試玩幣不記錄
			if (coinInfo.getCoinType() == CoinType.TRIAL) {
				coinInfo = coinLister.getNextCoin(it);
				continue;
			}

			if (param.getChangeWay().isDailyBet()) {
				CharacterInfoLogDAO.saveOrUpdateCharacterDaily
				(
						param.getPlayerId(),
						param.getAccountId(),
						param.getPlayerName(),
						coinInfo.getChangeValue(),
						BigDecimal.ZERO
				);
			} else if (param.getChangeWay().isDailyScore()) {
				CharacterInfoLogDAO.saveOrUpdateCharacterDaily
				(
						param.getPlayerId(),
						param.getAccountId(),
						param.getPlayerName(),
						BigDecimal.ZERO,
						coinInfo.getChangeValue()
				);
			}

			coinInfo = coinLister.getNextCoin(it);
		}
	}
	
	public boolean isFromWeb() {
		return isFromWeb;
	}

	public void setFromWeb(boolean isFromWeb) {
		this.isFromWeb = isFromWeb;
	}

}
